Skip to content

net-gateway: tag TLS handshake failures with the peer's alert - #708

Merged
nikhilbirmiwal-pplx merged 2 commits into
mainfrom
nikhilb/gateway-tls-alert-tag
Oct 20, 2026
Merged

nikhilbirmiwal-pplx merged 2 commits into
mainfrom
nikhilb/gateway-tls-alert-tag

Conversation

@nikhilbirmiwal-pplx

@nikhilbirmiwal-pplx nikhilbirmiwal-pplx commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

gateway.tls.handshake has an alert tag, but TlsFailure::new always set it to none and nothing ever filled it in. A guest that rejects the interception chain (sends unknown_ca / bad_certificate) was recorded exactly like a guest that disconnects or resets mid-handshake: outcome:error, reason:io, alert:none.

Change

  • When a handshake (or an established inspected connection) fails, read the fatal alert the peer sent. tokio-rustls returns an io::Error wrapping rustls::Error::AlertReceived(desc).
  • Tag it with the alert's numeric wire value from RFC 8446 §6, for example alert:48 (unknown_ca), alert:42 (bad_certificate) or alert:46 (certificate_unknown). The value fits in one byte, so the tag is bounded.
  • none still means the peer sent no alert.
  • The tls_alert log field on tls_handshake_error, gateway_boundary_failure and tls_connection_error carries the same number.
  • reason and every other tag are unchanged.
  • Removed the unused alert_class field.

The tag reports alerts the peer sent. Alerts the gateway itself sends (for example when origin certificate verification fails) aren't surfaced by rustls in a general form, so they're out of scope here.

Validation

  • cargo fmt --all -- --check passes.
  • cargo clippy -p pplx-space-net-gateway -p pplx-space-metrics --all-targets -- -D warnings passes.
  • Gitleaks on the staged diff found nothing.
  • No tests added.

Rollout note

This doesn't add a new metric or tag key; the alert tag just gets new values. If a deployment allowlists tags for gateway.tls.handshake, alert must be on that allowlist.

gateway.tls.handshake carried an `alert` tag that was always `none`, so a
guest rejecting the interception chain was indistinguishable from a guest
that disconnected or reset mid-handshake: both were `reason:io`.

Read the fatal alert rustls reports as `Error::AlertReceived` out of the
tokio-rustls I/O error and tag it with its IANA TLS Alerts registry name
(`unknown_ca`, `bad_certificate`, ...), keyed by wire value. Codepoints the
registry does not assign are tagged with their decimal value. The same name
now fills the `tls_alert` log field on handshake and established-connection
failures. `reason` is unchanged.
Report the received alert as its numeric wire value (RFC 8446 section 6) on the metric tag and log field instead of a registry name.
@kumarpallav-pplx
kumarpallav-pplx self-requested a review October 20, 2026 17:34
@nikhilbirmiwal-pplx
nikhilbirmiwal-pplx added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit bc9772e Oct 20, 2026
20 checks passed
@nikhilbirmiwal-pplx
nikhilbirmiwal-pplx deleted the nikhilb/gateway-tls-alert-tag branch October 20, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants